﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Runtime.Serialization;

using SynapseGaming.LightingSystem.Core;
using SynapseGaming.LightingSystem.Editor;
using SynapseGaming.LightingSystem.Lights;
using SynapseGaming.LightingSystem.Rendering;

using Jitter;
using Jitter.Collision;
using Jitter.Collision.Shapes;
using Jitter.Dynamics;
using Jitter.Forces;
using Jitter.LinearMath;

namespace SunburnJitter
{
    /// <summary>
    /// Component for capsule shaped physical objects
    /// </summary>
    public class CapsuleRigidBodyComponent : RigidBodyComponent
    {
        private float _length;
        /// <summary>
        /// The length/height of the capsule object.
        /// </summary>
        public float Length { get { return _length; } set { _length = value; RigidBody.Shape = new CapsuleShape(_length, _radius); } }

        private float _radius;
        /// <summary>
        /// The radius of the capsule.
        /// </summary>
        public float Radius { get { return _radius; } set { _radius = value; RigidBody.Shape = new CapsuleShape(_length, _radius); } }

        /// <summary>
        /// Initializes the capsule shaped component.
        /// </summary>
        /// <param name="length">The length/height of the capsule object</param>
        /// <param name="radius">The radius of the capsule object</param>
        public CapsuleRigidBodyComponent( float length, float radius)
        {
            _length = length;
            _radius = radius;
        }

        /// <summary>
        /// Initializes the capsule shaped component.
        /// </summary>
        /// <param name="length">The length/height of the capsule object</param>
        /// <param name="radius">The radius of the capsule object</param>
        /// <param name="localPos">The local position of the shape</param>
        public CapsuleRigidBodyComponent(float length, float radius, Vector3 localPos)
        {
            _length = length;
            _radius = radius;
            LocalPosition = localPos;
        }   
        
        /// <summary>
        /// Initializes the capsule shaped component.
        /// </summary>
        /// <param name="length">The length/height of the capsule object</param>
        /// <param name="radius">The radius of the capsule object</param>
        /// <param name="localPos">The local position of the shape</param>
        /// <param name="localOrientation">The local orientation of the shape</param>
        public CapsuleRigidBodyComponent(float length, float radius, Vector3 localPos, Vector3 localOrientation)
        {
            _length = length;
            _radius = radius;
            LocalPosition = localPos;
            LocalOrientation = localOrientation;
        }
        
        public override void OnInitialize()
        {
            RigidBody = new RigidBody(new CapsuleShape(_length, _radius));
            base.OnInitialize();
            RigidBody.Position = startPosition.ToJVector();
            RigidBody.Orientation = Matrix.CreateFromQuaternion(startOrientation).ToJitterMatrix();
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            SerializationHelper.SerializeFieldOrEnum(ref _length, info, "CapsuleLength");
            SerializationHelper.SerializeFieldOrEnum(ref _radius, info, "CapsuleRadius");

            base.GetObjectData(info, context);
        }

        public override void SetObjectData(SerializationInfo info, StreamingContext context)
        {
            SerializationHelper.DeserializeField(ref _length, info, "CapsuleLength", true);
            SerializationHelper.DeserializeField(ref _radius, info, "CapsuleRadius", true);

            base.SetObjectData(info, context);
        }
    }
}
